#include "sysproc.h"
#include "proc.h"
#include "riscv.h"
#include "stdio.h"
#include "mmu.h"
#include "dbg.h"

#include "fs/fat32.h"
#include "fs/file.h"

extern dirent_t root;

extern int runOver;

void
sysproc_exit(int status) {
    proc_t* p = getCurrentProc();
    // for(int i = 0; i < N_OPEN_FILE; i++)
    // {
    //     if(p->openFiles[i])
    //     {
    //         file_t *fd = p->openFiles[i];
    //         // __file_close(fd);
    //         p->openFiles[i] = 0;
    //     }
    // }
    p->openFiles[STDIN] = (file_t*)STDIN_PTR;
    p->openFiles[STDOUT] = (file_t*)STDOUT_PTR;
    p->openFiles[STDERR] = (file_t*)STDERR_PTR;
    if (p->cwd != &root) {
        __fat32_put(p->cwd);
        p->cwd = &root;
    }
    if (p->isForked) {
        spinlock_acquire(&p->lk);
        proc_t* parent_p = p->parent;
        spinlock_release(&p->lk);
        spinlock_acquire(&parent_p->lk);
        spinlock_acquire(&p->lk);
        reparent(p);
        proc_wakeup(parent_p);
        p->xstatus = status;
        p->state = ZOMBIE;
        spinlock_release(&parent_p->lk);
        spinlock_release(&p->lk);
    } else {
        spinlock_acquire(&p->lk);
        p->xstatus = status;
        p->state = ZOMBIE;
        spinlock_release(&p->lk);
    }
    runOver = TRUE;
    __DEBUG_INFO(sysproc_exit() over);
    sched();
}

pid_t
sysproc_getpid(void) {
    return getCurrentProc()->pid;
}    


pid_t
sysproc_getppid(void) {
    proc_t* p = getCurrentProc();
    if (p->parent) {
        return p->parent->pid;
    }
    return 0;
}

pid_t
sysproc_clone(uint64_t flags, void* stack, pid_t ptid, uint64_t tls, pid_t ctid) {
    if(flags == SIGCHLD)
    {
        fork();
    }
    else
    {
        
    }
}

int
sysproc_execve(char* path, char* argv, char* envp) {
    proc_t* p = getCurrentProc();
    elf_load(p, path);
    p->trapFrame->sp = p->size;
    // p->trapFrame->a1 = sp ? why
    p->heap = NULL;
    // TODO: fs
    w_satp(PAGE_TABLE_SHIFT(p->kpageTable));
    sfenve_vma();
    return 0;
}

pid_t
sysproc_wait4(pid_t pid, int* status, int options) {
    return wait(pid);
}

int
sysproc_sched_yield(void) {
    yield();
    return 1;
}

address_t sysproc_times(void * mytimes)
{
    tms_t *user = (tms_t *)mytimes;
    proc_t *p = getCurrentProc();
    user->tms_stime = p->tms.tms_stime;
    user->tms_cstime = p->tms.tms_cstime;
    user->tms_cutime = p->tms.tms_cutime;
    user->tms_utime = p->tms.tms_utime;
    return (address_t)mytimes;
}

uint64_t sysproc_nanosleep(void)
{

}


